
#include <json-c/json.h>
#include "test_json_c.h"
#include "mytest_log.h"

static const char kKeyResp[] = "response";
static const char kKeyResult[] = "result";
static const char kKeyAppName[] = "app_name";
static const char kKeyAppVersion[] = "app_version";
static const char kKeyAppDecription[] = "app_decription";
static const char kKeyCheckError[] = "check_error";
static const char kKeyUpdateError[] = "update_error";

void on_notify_check_result(const std::vector<StAppInfo> & vct)
{
    json_object *jarray = json_object_new_array();
    json_object* json_tmp;

    for (auto vec : vct) {
        json_tmp = json_object_new_object();
        json_object_object_add(json_tmp, kKeyAppName, json_object_new_string(vec.strName.c_str()));
        json_object_object_add(json_tmp, kKeyAppVersion, json_object_new_string(vec.strVersion.c_str()));
        json_object_object_add(json_tmp, kKeyAppDecription, json_object_new_string(vec.strReadme.c_str()));
        json_object_array_add(jarray, json_tmp);
    }

    send_event(Event_Check, jarray);
}

void on_notify_update_result(const _tstring &appname, const bool &is_ok)
{
    json_object* object = json_object_new_object();

    json_object_object_add(object, kKeyAppName, json_object_new_string(appname.c_str()));
    json_object_object_add(object, kKeyResult, json_object_new_boolean(is_ok));

    send_event(Event_Update, object);
}

void on_notify_download_result(const _tstring &appname, const bool &is_ok)
{
    json_object* object = json_object_new_object();
    json_object_object_add(object, kKeyAppName, json_object_new_string(appname.c_str()));
    json_object_object_add(object, kKeyResult, json_object_new_boolean(is_ok));

    send_event(Event_Download, object);
}

void on_notify_end()
{
    json_object *object = json_object_new_object();
    json_object_object_add(object, "end", json_object_new_string("end"));

    send_event(Event_End, object);
}

void on_notify_check_error(const _tstring &err)
{
    json_object *object = json_object_new_object();
    json_object_object_add(object, kKeyCheckError, json_object_new_string(err.c_str()));

    send_event(Event_Error, object);
}

void on_notify_update_error(const _tstring &err)
{
    json_object *object = json_object_new_object();
    json_object_object_add(object, kKeyUpdateError, json_object_new_string(err.c_str()));

    send_event(Event_Error, object);
}

void send_event(const EventType& type, json_object *object)
{
    json_object *jo = json_object_new_object();
    json_object_object_add(jo, kKeyResp, object);

    _tstring str = json_object_get_string(jo);
    LOG_DEBUG("Send-msg : [%s]", str.c_str());

    recv_event(type, jo);
    json_parse(str);
}

void recv_event(const EventType &type, json_object *object)
{
    json_object *j_val;
    if(!json_object_object_get_ex(object, kKeyResp, &j_val)) {
        LOG_ERROR("libjota Not right response string [%s]", json_object_get_string(object));
        return;
    }
    LOG_DEBUG("Resp-msg : [%s]", json_object_get_string(j_val));

    switch(type)
    {
    case Event_Check:
        {
            std::vector<StAppInfo> vct;
            int len = json_object_array_length(j_val);
            if (len <= 0) break;

            json_object* tmp;
            for (int i = 0; i < len; ++i) {
                StAppInfo st;
                json_object *json_tmp = json_object_array_get_idx(j_val, i);

                if (json_object_object_get_ex(json_tmp, kKeyAppName, &tmp)) {
                    st.strName =  json_object_get_string(tmp);
                }
                if (json_object_object_get_ex(json_tmp, kKeyAppVersion, &tmp)) {
                    st.strVersion = json_object_get_string(tmp);
                }
                if (json_object_object_get_ex(json_tmp, kKeyAppDecription, &tmp)) {
                    st.strReadme = json_object_get_string(tmp);
                }

                st.st_print();
                vct.push_back(st);
                json_object_put(json_tmp);
            }

            json_object_put(tmp);
        }
        break;
    case Event_Update:
        {
            json_object *one;
            _tstring name, strb;
            if (json_object_object_get_ex(j_val, kKeyAppName, &one)) {
                name = json_object_get_string(one);
            }
            if (json_object_object_get_ex(j_val, kKeyResult, &one)) {
                strb = json_object_get_string(one);
            }

            json_object_put(one);


            bool result = (strb == "true") ? true : false;
            LOG_DEBUG("Update : name [%s] result [%d]", name.c_str(), result);
        }
        break;
    case Event_Download:
        {
            json_object *one;
            _tstring name, strb;
            if (json_object_object_get_ex(j_val, kKeyAppName, &one)) {
                name = json_object_get_string(one);
            }
            if (json_object_object_get_ex(one, kKeyResult, &one)) {
                strb = json_object_get_string(one);
            }
            json_object_put(one);

            bool result = (strb == "true") ? true : false;
            LOG_DEBUG("Download : name [%s] result [%d]", name.c_str(), result);
        }
        break;
    case Event_End:
        {
            LOG_DEBUG("End : the end !!!");
        }
        break;
    case Event_Error:
        {
            json_object *one;
            _tstring error;

            if (json_object_object_get_ex(j_val, kKeyCheckError, &one)) {
                error = json_object_get_string(one);
            }
            if (json_object_object_get_ex(j_val, kKeyUpdateError, &one)) {
                error = json_object_get_string(one);
            }

            LOG_DEBUG("Error : msg [%s]", error.c_str());
        }
        break;
    default :
        break;
    }
    json_object_put(j_val);
    json_object_put(object);
}


bool make_urlpost_Json(const StUpdateInfo & stUpdateInfo, _tstring & strJson)
{
    json_object *jobject = json_object_new_object();
    json_object_object_add(jobject, JOTASYS_JSONARG_VERSION, json_object_new_string(stUpdateInfo.stSys.strVersion.c_str()));

    json_object *jarray = json_object_new_array();
    json_object* json_tmp;

    for (auto vec : stUpdateInfo.vctApps) {
        json_tmp = json_object_new_object();
        json_object_object_add(json_tmp, JOTAAPP_POSTJSON_NAME, json_object_new_string(vec.strName.c_str()));
        json_object_object_add(json_tmp, JOTAAPP_POSTJSON_VERSION, json_object_new_string(vec.strVersion.c_str()));
        json_object_array_add(jarray, json_tmp);
    }

    json_object_object_add(jobject, JOTASYS_JSONARG_APPLICATION, jarray);
    json_object_object_add(jobject, JOTASYS_JSONARG_SN, json_object_new_string(stUpdateInfo.stSys.strSN.c_str()));

    strJson = json_object_get_string(jobject);

    json_object_put(jobject);

    return true;
}

bool parse_afmresp_Json(_tcstring &strJson, std::vector<StAppInfo> &vct)
{
    struct json_tokener *tokener = json_tokener_new();

    json_object* object = json_tokener_parse_ex(tokener, strJson.c_str(), strJson.length());
    if (NULL == object) {
        LOG_DEBUG("json-c parse error !~");
        return false;
    }

    if (json_object_get_type(object) != json_type_array) {
        LOG_DEBUG("json-c type wrong !~");
        return false;
    }

    vct.clear();

    int len = json_object_array_length(object);
    if (len <= 0) return false;

    json_object* tmp;
    for (int i = 0; i < len; ++i) {
        StAppInfo st;
        json_object *json_tmp = json_object_array_get_idx(object, i);

        if (json_object_object_get_ex(json_tmp, JOTAAPP_JSONARG_PORT, &tmp)) {
            st.nPort =  json_object_get_int64(tmp);
        }
        if (json_object_object_get_ex(json_tmp, JOTAAPP_JSONARG_VERSION, &tmp)) {
            st.strVersion = json_object_get_string(tmp);
        }
        if (json_object_object_get_ex(json_tmp, JOTAAPP_JSONARG_NAME, &tmp)) {
            st.strName = json_object_get_string(tmp);
        }
        if (json_object_object_get_ex(json_tmp, JOTAAPP_JSONARG_ID, &tmp)) {
            st.strId = json_object_get_string(tmp);
        }

        vct.push_back(st);
        st.st_print();

        json_object_put(json_tmp);
    }

    json_object_put(tmp);
    json_tokener_free(tokener);

    return true;
}

bool parse_installresp_json(_tcstring &strJson, _tstring &strId)
{
    struct json_tokener *tokener = json_tokener_new();

    json_object* object = json_tokener_parse_ex(tokener, strJson.c_str(), strJson.length());
    if (NULL == object) {
        LOG_DEBUG("json-c parse error !~");
        return false;
    }

    if (json_object_get_type(object) != json_type_object) {
        LOG_DEBUG("json-c type wrong !~");
        return false;
    }


    json_object *json_tmp;
    if (json_object_object_get_ex(object, JOTAAPP_CMDJSON_ADD, &json_tmp)) {
        strId =  json_object_get_string(json_tmp);
    }

    json_tokener_free(tokener);

    return true;
}

bool parse_webresp_json(_tcstring &strJson, std::vector<StAppInfo> & vct)
{
    struct json_tokener *tokener = json_tokener_new();

    json_object* object = json_tokener_parse_ex(tokener, strJson.c_str(), strJson.length());
    if (NULL == object) {
        LOG_DEBUG("json-c parse error !~");
        return false;
    }

    if (json_object_get_type(object) != json_type_array) {
        LOG_DEBUG("json-c type wrong !~");
        return false;
    }

    vct.clear();

    int len = json_object_array_length(object);
    if (len <= 0) return false;

    json_object* tmp;
    for (int i = 0; i < len; ++i) {
        StAppInfo stApp;
        json_object *json_tmp = json_object_array_get_idx(object, i);

        if (json_object_object_get_ex(json_tmp, JOTAAPP_WEBJSON_NAME, &tmp)) {
            stApp.strName =  json_object_get_string(tmp);
        }
        if (json_object_object_get_ex(json_tmp, JOTAAPP_WEBJSON_VERSION, &tmp)) {
            stApp.strVersion = json_object_get_string(tmp);
        }
        if (json_object_object_get_ex(json_tmp, JOTAAPP_WEBJSON_URL, &tmp)) {
            _tstring url = JOTA_CURL_HTTP_PORT/*g_getprop(JOTA_SYSPROP_URLKEY)*/;
            if (url.empty()) {
                url = JOTA_CURL_HTTP_PORT;
            }
            stApp.strUrl = url + JOTA_CURL_DLWD_KEY + json_object_get_string(tmp);
        }
        if (json_object_object_get_ex(json_tmp, JOTAAPP_WEBJSON_MD5, &tmp)) {
            stApp.strMD5 = json_object_get_string(tmp);
        }

        if (json_object_object_get_ex(json_tmp, JOTAAPP_WEBJSON_README, &tmp)) {
            stApp.strReadme = json_object_get_string(tmp);
        }

        vct.push_back(stApp);

        json_object_put(json_tmp);
    }

    json_object_put(tmp);
    json_tokener_free(tokener);

    return true;
}

void json_parse(const _tstring & str)
{
    struct json_tokener *tokener = json_tokener_new();

    json_object* object = json_tokener_parse_ex(tokener, str.c_str(), str.length());

    if (nullptr == object) {
        LOG_DEBUG("parse string failed !");
        return;
    }

    LOG_DEBUG("json__parse-msg : [%s]", json_object_get_string(object));
    // Free json_tokener
    json_tokener_free(tokener);
}
